package com.easylinkin.linkappapi.facerecognition.service.ai.impl;

import com.easylinkin.linkappapi.facerecognition.entity.FacePhoto;
import com.easylinkin.linkappapi.facerecognition.service.FacePhotoService;
import com.easylinkin.linkappapi.facerecognition.service.ai.FaceRecognitionService;
import com.easylinkin.linkappapi.facerecognition.service.rest.KoalaManagementClientService;
import com.easylinkin.linkappapi.facerecognition.service.rest.KoalaRecognizeClientService;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import retrofit2.Call;
import retrofit2.Response;

import java.io.File;
import java.io.IOException;
import java.util.*;

@Service
@ConditionalOnProperty(value = "ai.face.platform", havingValue = "koala")
public class KoalaFaceRecognitionService implements FaceRecognitionService {

    private static final Logger log = LoggerFactory.getLogger(KoalaFaceRecognitionService.class);

    private static final Gson gson = new Gson();

    @Value("${ai.face.koala.username}")
    private String username;

    @Value("${ai.face.koala.password}")
    private String password;

    @Value("${ai.face.koala.token}")
    private String screenToken;

    private static Map<String, RequestBody> koalaLoginRequest = null;

    @Autowired
    private KoalaManagementClientService koalaManagementClient;

    @Autowired
    private KoalaRecognizeClientService koalaRecognizeClient;

    @Autowired
    private FacePhotoService facePhotoService;


    /**
     * koala平台可以忽略userId字段，该字段为适配百度平台所需的
     * <p>
     * 1. 先上传底库照片
     * 2. 基于底库照片的ID列表创建用户
     */
    @Override
    public Optional<JsonObject> registerUser(String username, MultipartFile[] photos, List<String> faceTokens, Map<String, String> photoUrls) {

        // 1. 先调用登录接口获取cookie
        Call<JsonObject> loginCall = koalaManagementClient.login(buildLoginRequest());
        try {
            Response<JsonObject> loginResponse = loginCall.execute();
            if (!koalaRequestSuccess(loginResponse)) {
                return Optional.of(loginResponse.body());
            }
        } catch (IOException e) {
            log.error("koala login error {}", e.getMessage());
            return Optional.empty();
        }

        // 2. 上传底库照片
        List<Integer> photoIds = new ArrayList<>();
        for (MultipartFile photo : photos) {
            File tmp = null;
            try {
                tmp = new File(System.getProperty("java.io.tmpdir") + File.separator + photo.getOriginalFilename());
                photo.transferTo(tmp);
                RequestBody rb = RequestBody.create(MediaType.parse("image/jpeg"), tmp);
                MultipartBody.Part p = MultipartBody.Part.createFormData("photo", photo.getOriginalFilename(), rb);
                Call<JsonObject> photoCall = koalaManagementClient.subjectPhoto(p);

                Response<JsonObject> photoResponse = photoCall.execute();
                if (koalaRequestSuccess(photoResponse)) {
                    // 取出上传成功的图片的ID
                    int photoId = photoResponse.body().get("data").getAsJsonObject().get("id").getAsInt();
                    FacePhoto facePhoto = new FacePhoto();
                    facePhoto.setPhotoId(String.valueOf(photoId));
                    facePhoto.setPhotoUrl(photoUrls.get(photo.getOriginalFilename()));
                    facePhotoService.save(facePhoto);
                    photoIds.add(photoId);
                } else {
                    return Optional.of(photoResponse.body());
                }
            } catch (IOException e) {
                log.error("upload photo to koala error {}", e.getMessage());
                return Optional.empty();
            } finally {
                if (tmp != null) {
                    tmp.delete();
                }
            }
        }

        // 3. 注册用户
        JsonObject subjectObj = new JsonObject();
        subjectObj.addProperty("subject_type", 0); // 必填项，固定使用员工类型
        subjectObj.addProperty("name", username);
        subjectObj.add("photo_ids", gson.toJsonTree(photoIds));

        Call<JsonObject> subjectCall = koalaManagementClient.subject(subjectObj);
        try {
            Response<JsonObject> subjectResponse = subjectCall.execute();

            return Optional.of(subjectResponse.body());

        } catch (IOException e) {
            log.error("koala subject error {}", e.getMessage());
        }

        return Optional.empty();
    }

    @Override
    public Optional<JsonObject> updateUser(String username, String subjectId, String userId, MultipartFile[] photos, List<String> imgs, Map<String, String> photoUrls) {
        // 1. 先调用登录接口获取cookie
        Call<JsonObject> loginCall = koalaManagementClient.login(buildLoginRequest());
        try {
            Response<JsonObject> loginResponse = loginCall.execute();
            if (!koalaRequestSuccess(loginResponse)) {
                return Optional.of(loginResponse.body());
            }
        } catch (IOException e) {
            log.error("koala login error {}", e.getMessage());
            return Optional.empty();
        }

        // 2. 上传底库照片
        List<Integer> photoIds = new ArrayList<>();
        for (MultipartFile photo : photos) {
            File tmp = null;
            try {
                tmp = new File(System.getProperty("java.io.tmpdir") + File.separator + photo.getOriginalFilename());
                photo.transferTo(tmp);
                RequestBody rb = RequestBody.create(MediaType.parse("image/jpeg"), tmp);
                MultipartBody.Part p = MultipartBody.Part.createFormData("photo", photo.getOriginalFilename(), rb);
                Call<JsonObject> photoCall = koalaManagementClient.subjectPhoto(p);

                Response<JsonObject> photoResponse = photoCall.execute();
                if (koalaRequestSuccess(photoResponse)) {
                    // 取出上传成功的图片的ID
                    int photoId = photoResponse.body().get("data").getAsJsonObject().get("id").getAsInt();
                    FacePhoto facePhoto = new FacePhoto();
                    facePhoto.setPhotoId(String.valueOf(photoId));
                    facePhoto.setPhotoUrl(photoUrls.get(photo.getOriginalFilename()));
                    facePhotoService.save(facePhoto);
                    photoIds.add(photoId);
                } else {
                    return Optional.of(photoResponse.body());
                }
            } catch (IOException e) {
                log.error("upload photo to koala error {}", e.getMessage());
                return Optional.empty();
            } finally {
                if (tmp != null) {
                    tmp.delete();
                }
            }
        }

        // 3. 更新用户
        JsonObject subjectObj = new JsonObject();
        subjectObj.addProperty("subject_type", 0); // 必填项，固定使用员工类型
        subjectObj.addProperty("name", username);
        subjectObj.add("photo_ids", gson.toJsonTree(photoIds));

        Call<JsonObject> subjectCall = koalaManagementClient.updateSubject(subjectObj, subjectId);
        try {
            Response<JsonObject> subjectResponse = subjectCall.execute();

            return Optional.of(subjectResponse.body());

        } catch (IOException e) {
            log.error("koala subject error {}", e.getMessage());
        }

        return Optional.empty();
    }

    @Override
    public boolean deleteUser(String subjectId) {

        // 1. 先调用登录接口获取cookie
        Call<JsonObject> loginCall = koalaManagementClient.login(buildLoginRequest());
        try {
            Response<JsonObject> loginResponse = loginCall.execute();
            if (!koalaRequestSuccess(loginResponse)) {
                return false;
            }
        } catch (IOException e) {
            log.error("koala login error {}", e.getMessage());
            return false;
        }

        // 2. 删除考拉用户
        //MultipartBody.Part rb = MultipartBody.Part.createFormData("subject_id", subjectId);
        Call<JsonObject> deleteCall = koalaManagementClient.deleteSubject(subjectId);
        Response<JsonObject> photoResponse = null;
        try {
            photoResponse = deleteCall.execute();
            if (!koalaRequestSuccess(photoResponse)) {
                return false;
            }
        } catch (IOException e) {
            log.error("koala delete user error {}", e.getMessage());
            return false;
        }

        return true;
    }

    /**
     * 检查考拉的响应结果是否成功
     */
    private boolean koalaRequestSuccess(Response<JsonObject> response) {

        if (response.isSuccessful()) {
            if (response.body() != null) {
                return response.body().get("code").getAsInt() == 0;
            }
        }

        return false;
    }

    /**
     * koala 的请求需要先执行登录请求以创建cookie，后续其他请求才能成功
     */
    private Map<String, RequestBody> buildLoginRequest() {
        if (koalaLoginRequest == null) {
            koalaLoginRequest = new HashMap<>();

            koalaLoginRequest.put("username", RequestBody.create(MediaType.parse("multipart/form-data"), username));
            koalaLoginRequest.put("password", RequestBody.create(MediaType.parse("multipart/form-data"), password));
        }

        return koalaLoginRequest;
    }

    @Override
    public Optional<JsonObject> recognize(File photo) {

        // 1. 先调用登录接口获取cookie
        Call<JsonObject> loginCall = koalaManagementClient.login(buildLoginRequest());
        try {
            Response<JsonObject> loginResponse = loginCall.execute();
            if (!koalaRequestSuccess(loginResponse)) {
                return Optional.of(loginResponse.body());
            }
        } catch (IOException e) {
            log.error("koala login error {}", e.getMessage());
            return Optional.empty();
        }

        RequestBody rb = RequestBody.create(MediaType.parse("image/jpeg"), photo);
        MultipartBody.Part p = MultipartBody.Part.createFormData("image", photo.getName(), rb);

        RequestBody token = RequestBody.create(MediaType.parse("multipart/form-data"), screenToken);

        Call<JsonObject> recognize = koalaRecognizeClient.recognize(p, token);
        try {
            Response<JsonObject> recognizeResponse = recognize.execute();
            if (recognizeResponse.body() != null && Objects.nonNull(recognizeResponse.body().getAsJsonObject("person"))) {
                return Optional.of(recognizeResponse.body());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return Optional.empty();
    }
}
